package com.cskaoyan.wordmemorize.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cskaoyan.wordmemorize.common.constant.ResultCodeEnum;
import com.cskaoyan.wordmemorize.common.exception.ExcelParseException;
import com.cskaoyan.wordmemorize.converter.VocConverter;
import com.cskaoyan.wordmemorize.dao.entity.*;
import com.cskaoyan.wordmemorize.dao.mapper.*;
import com.cskaoyan.wordmemorize.dto.admin.*;
import com.cskaoyan.wordmemorize.dto.app.DisplayBookVocDTO;
import com.cskaoyan.wordmemorize.dto.app.DisplayChapterDTO;
import com.cskaoyan.wordmemorize.dto.app.UserBookStatisticsDTO;
import com.cskaoyan.wordmemorize.dto.app.UserExampleSentenceDTO;
import com.cskaoyan.wordmemorize.request.*;
import com.cskaoyan.wordmemorize.service.FileUploadService;
import com.cskaoyan.wordmemorize.service.VocService;
import com.cskaoyan.wordmemorize.service.excel.VocExcelSaver;
import com.cskaoyan.wordmemorize.service.excel.VocExcelValidator;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class VocServiceImpl implements VocService {

    @Resource
    VocConverter vocConverter;

    @Autowired
    VocMapper vocMapper;

    @Autowired
    VocChapBookMapper vocChapBookMapper;

    @Autowired
    VocMeaningMapper vocMeaningMapper;
    @Autowired
    UserFavoriteMapper userFavoriteMapper;

    @Autowired
    ExampleSentenceMapper exampleSentenceMapper;


    @Autowired
    VocBookMapper vocBookMapper;


    @Autowired
    VocChapterMapper vocChapterMapper;
    @Autowired
    UserVocExampleSentenceMapper userVocExampleSentenceMapper;

    @Autowired
    UserMapper userMapper;

    @Autowired
    VocExcelValidator vocExcelValidator;

    @Value("${excel.template.vocabulary.path}")
    private String templatePath;

    @Autowired
    VocExcelSaver vocExcelSaver;

    @Autowired
    FileUploadService fileUploadService;




    @Override
    @Transactional
    public PageDTO<VocDTO> getVocabularies(VocPageRequest pageQuery) {
        int offset = (pageQuery.getPageNum() - 1) * pageQuery.getCount();
        int limit = pageQuery.getCount();
        Page<VocDO> page = new Page<>(pageQuery.getPageNum(), pageQuery.getCount());
        QueryWrapper<VocChapBookDO> wrapper = new QueryWrapper<>();
        wrapper.eq(pageQuery.getChapterId() != null,"chapter_id",pageQuery.getChapterId());
        wrapper.eq(pageQuery.getBookId() != null,"book_id",pageQuery.getBookId());
        wrapper.like(pageQuery.getKeyword() != null,"voc_name",pageQuery.getKeyword());
        List<VocChapBookDO> vocChapBookDOS = vocChapBookMapper.selectList(wrapper);
        List<Long> ids = vocChapBookDOS.stream().map(vocChapBookDO -> vocChapBookDO.getVocId()).collect(Collectors.toList());

//        IPage<VocDO> vocDOIPage = vocMapper.selectPage(page,wrapper);
        List<VocDO> records = vocMapper.getVocList(pageQuery,ids);
        long total = records.size();
        PageDTO<VocDTO> vocDTOPageDTO = vocConverter.vocList2Page(records, total);
        return vocDTOPageDTO;
    }

    @Override
    @Transactional
    public void addVoc(VocCommand command) {

        // 将单词的基本信息保存到voc表中
        VocDO vocDO = vocConverter.command2VocDO(command);
        vocMapper.insert(vocDO);

        // 保存关系
        List<VocChapBookDO> relations = vocConverter.commands2VocChapBookDOs(command.getRelations());
        if (relations != null) {
            for (VocChapBookDO vocChapBookDO : relations) {
                // 设置单词id
                vocChapBookDO.setVocId(vocDO.getId());
                vocChapBookMapper.insert(vocChapBookDO);

                // 修改书籍和章节关联的单词数量
                if (vocChapBookDO.getChapterId() != null) {
                    // 关联到了一个章节
                    LambdaUpdateWrapper<VocChapterDO> vocChapterWrapper = new LambdaUpdateWrapper<>();
                    vocChapterWrapper.eq(VocChapterDO::getId, vocChapBookDO.getChapterId())
                            // set voc_count = voc_count + 1
                            .setSql("voc_count = voc_count + 1");

                    vocChapterMapper.update(null, vocChapterWrapper);
                }


                // 更新书籍关联的单词数量
                // 关联到了一个章节
                LambdaUpdateWrapper<VocBookDO> vocBookWrapper = new LambdaUpdateWrapper<>();
                vocBookWrapper.eq(VocBookDO::getId, vocChapBookDO.getBookId())
                        // set voc_count = voc_count + 1
                        .setSql("voc_count = voc_count + 1");
                vocBookMapper.update(null, vocBookWrapper);

            }
        }


        // 保存释义
        List<VocMeaningCommand> interpretations = command.getInterpretations();
        if (interpretations != null) {
            List<VocMeaningDO> vocMeaningDOs = vocConverter.commands2VocMeaningDOs(interpretations);
            for (VocMeaningDO vocMeaningDO : vocMeaningDOs) {
                vocMeaningDO.setVocId(vocDO.getId());
                vocMeaningMapper.insert(vocMeaningDO);

            }
        }



        // 保存例句
        List<ExampleSentenceCommand> examples = command.getExamples();
        if (examples != null) {
            List<ExampleSentenceDO> exampleSentenceDOS = vocConverter.commands2ExampleSentenceDOs(examples);
            for (ExampleSentenceDO exampleSentenceDO : exampleSentenceDOS) {
                exampleSentenceDO.setVocId(vocDO.getId());
                exampleSentenceMapper.insert(exampleSentenceDO);
            }
        }



    }

    @Override
    @Transactional
    //修改单词
    public void updateVoc(VocCommand command) {
        VocDO vocDO = vocConverter.command2VocDO(command);
        // 跟新单词本身的信息
        vocMapper.updateById(vocDO);

        // 处理关系
        handleRelations(command, vocDO);
        // 更新每一个释义
        if (command.getInterpretations() == null) {
            return;
        }
        // 处理释义
        handleMeanings(command, vocDO);

        if (command.getExamples() == null) {
            return;
        }
        // 处理例句
        handleExampleSentences(command, vocDO);
    }

    private void handleExampleSentences(VocCommand command, VocDO vocDO) {

        List<ExampleSentenceDO> exampleSentenceDOs = vocConverter.commands2ExampleSentenceDOs(command.getExamples());
        exampleSentenceDOs.forEach(exampleSentenceDO -> {
            if (exampleSentenceDO.getId() == null) {
                // 新增
                exampleSentenceDO.setVocId(vocDO.getId());
                exampleSentenceMapper.insert(exampleSentenceDO);
                return;
            }
            // 更新
            exampleSentenceMapper.updateById(exampleSentenceDO);
        });
    }

    private void handleRelations(VocCommand command, VocDO vocDO) {
        // 前端上传的关系集合
        List<VocChapBookDO> vocChapBookDOs = vocConverter.commands2VocChapBookDOs(command.getRelations());
        if (CollectionUtils.isEmpty(vocChapBookDOs)) {
            return;
        }
        // 查询数据库中旧的关系id集合
        List<VocChapBookDO> vocRelationsFromDb = vocChapBookMapper.getVocRelations(vocDO.getId());

        updateOrInsertVocRelations(vocRelationsFromDb, vocChapBookDOs, vocDO);
    }

    private void handleMeanings(VocCommand command, VocDO vocDO) {
        // 删除释义
        LambdaQueryWrapper<VocMeaningDO> vocMeaningDOLambdaQueryWrapper = new LambdaQueryWrapper<>();
        vocMeaningDOLambdaQueryWrapper.eq(VocMeaningDO::getVocId, vocDO.getId());

        // 获取前端上传的释义
        List<VocMeaningDO> vocMeaningDOs = vocConverter.commands2VocMeaningDOs(command.getInterpretations());

        vocMeaningDOs.forEach(vocMeaningDO -> {
            if (vocMeaningDO.getId() == null) {
                vocMeaningDO.setVocId(vocDO.getId());
                vocMeaningMapper.insert(vocMeaningDO);
            }

            vocMeaningMapper.updateById(vocMeaningDO);
        });
    }

    private void updateOrInsertVocRelations(List<VocChapBookDO> vocRelationsFromDb, List<VocChapBookDO> vocChapBookDOs, VocDO vocDO) {
        // key:id
        // value:VocChapBookDO
        Map<Long, VocChapBookDO> vocChapBookMap = vocRelationsFromDb.stream()
                .collect(Collectors.toMap(vocChapBookDO -> vocChapBookDO.getId(), vocChapBookDO -> vocChapBookDO));
        // 一次判断每一个关系
        vocChapBookDOs.forEach(vocChapBookDO -> {
            if (vocChapBookDO.getId() == null) {
                // 新增
                vocChapBookDO.setVocId(vocDO.getId());
                vocChapBookMapper.insert(vocChapBookDO);
                if (vocChapBookDO.getChapterId() != null) {
                    // 有章节(此时一定是新增)
                    vocMapper.updateChapterVocCount(vocChapBookDO.getChapterId(), 1);
                }
                vocMapper.updateBookVocCount(vocChapBookDO.getBookId(), 1);
                return;
            }
            // 如果不是新增
            updateVocChapBook(vocChapBookDO, vocChapBookMap);
        });
    }

    private void updateVocChapBook(VocChapBookDO vocChapBookDO, Map<Long, VocChapBookDO> vocChapBookMap) {
        VocChapBookDO vocChapBookFromDb = vocChapBookMap.get(vocChapBookDO.getId());
        if (vocChapBookFromDb.getBookId() == vocChapBookDO.getBookId()) {
            if (vocChapBookFromDb.getChapterId() == vocChapBookDO.getChapterId()) {
                // 如果bookId和chapterId都没有变，那么单词数量不需要变
                return;
            }

            // chapterId变了，book的单词数量不需要变
            // 旧的章节单词数量-1
            vocMapper.updateChapterVocCount(vocChapBookFromDb.getChapterId(), -1);
            // 新的章节单词数量+1
            vocMapper.updateChapterVocCount(vocChapBookDO.getChapterId(), 1);
            // 更新关系
            vocChapBookMapper.updateById(vocChapBookDO);
            return;
        }

        // 说明改变了单词所属的书籍，那么书籍，章节的词汇数量都要跟着变
        // 旧的书籍单词数量-1
        vocMapper.updateBookVocCount(vocChapBookFromDb.getBookId(), -1);
        // 新的书籍单词数量+1
        vocMapper.updateBookVocCount(vocChapBookDO.getBookId(), 1);
        // 旧的章节单词数量-1
        vocMapper.updateChapterVocCount(vocChapBookFromDb.getChapterId(), -1);
        // 新的章节单词数量+1
        vocMapper.updateChapterVocCount(vocChapBookDO.getChapterId(), 1);
        vocChapBookMapper.updateById(vocChapBookDO);

    }

    @Override
    @Transactional
    //删除指定单词
    public DeleteVocOperateDTO deleteVocabulary(Long vocId) {
        // 删除单词本身
        VocDO vocDO = vocMapper.selectById(vocId);
        vocMapper.deleteById(vocId);

        LambdaUpdateWrapper<VocChapBookDO> vocChapterDOWrapper = new LambdaUpdateWrapper<>();
        vocChapterDOWrapper.eq(VocChapBookDO::getVocId, vocId);
        List<VocChapBookDO> vocChapBookDOs = vocChapBookMapper.selectList(vocChapterDOWrapper);
        if (!CollectionUtils.isEmpty(vocChapBookDOs)) {
            vocChapBookDOs.forEach(vocChapBookDO -> {
                if (vocChapBookDO.getChapterId()!= null) {
                    // 有章节
                    vocMapper.updateChapterVocCount(vocChapBookDO.getChapterId(), -1);
                }
                vocMapper.updateBookVocCount(vocChapBookDO.getBookId(), -1);
            });
        }

        // 删除关系
        LambdaQueryWrapper<VocChapBookDO> vocChapBookWrapper = new LambdaQueryWrapper<>();
        vocChapBookWrapper.eq(VocChapBookDO::getVocId, vocId);
        vocChapBookMapper.delete(vocChapBookWrapper);

        // 删除释义
        LambdaQueryWrapper<VocMeaningDO> meaningWrapper = new LambdaQueryWrapper<>();
        meaningWrapper.eq(VocMeaningDO::getVocId, vocId);
        vocMeaningMapper.delete(meaningWrapper);

        // 删除例句
        LambdaQueryWrapper<ExampleSentenceDO> exampleWrapper = new LambdaQueryWrapper<>();
        exampleWrapper.eq(ExampleSentenceDO::getVocId, vocId);
        exampleSentenceMapper.delete(exampleWrapper);

        return vocConverter.toDeleteVocOperateDTO(vocDO);
    }

    @Override
    @Transactional
    //*批量删除单词
    public List<DeleteVocOperateDTO> deleteVocabularies(BatchDeleteCommand command) {
        List<Long> ids = command.getIds().stream()
                .map(idStr -> Long.parseLong(idStr)).collect(Collectors.toList());
        List<VocDO> vocDOs = vocMapper.selectByIds(ids);
        int from = 0;
        for (int i = 0; i < ids.size(); i++) {
            if (i % 100 == 0 && i > 0) {
                List<Long> batchDeleteVocIds = ids.subList(from, i);
                batchDeleteVocs(batchDeleteVocIds);
                from = i;
            }
        }
        List<Long> batchDeleteVocIds = ids.subList(from, ids.size());
        if (batchDeleteVocIds.size() > 0) {
            batchDeleteVocs(batchDeleteVocIds);
        }
        return vocConverter.toDeleteVocOperateDTOs(vocDOs);
    }
    public void batchDeleteVocs(List<Long> batchDeleteVocIds) {
        // 删除单词
        vocMapper.deleteBatchIds(batchDeleteVocIds);
        // 删除关系
        LambdaQueryWrapper<VocChapBookDO> vocChapBookWrapper
                = new LambdaQueryWrapper<>();
        vocChapBookWrapper.in(VocChapBookDO::getVocId, batchDeleteVocIds);
        // 更新书籍，章节包含的单词数量
        updateVocCount(vocChapBookWrapper);
        // 删除关系
        vocChapBookMapper.delete(vocChapBookWrapper);
        // 删除释义
        LambdaQueryWrapper<VocMeaningDO> vocMeaningWrapper
                = new LambdaQueryWrapper<>();
        vocChapBookWrapper.in(VocChapBookDO::getVocId, batchDeleteVocIds);
        vocMeaningMapper.delete(vocMeaningWrapper);
        //删除例句
        LambdaQueryWrapper<ExampleSentenceDO> exampleWrapper
                = new LambdaQueryWrapper<>();
        exampleWrapper.in(ExampleSentenceDO::getVocId, batchDeleteVocIds);
        exampleSentenceMapper.delete(exampleWrapper);
    }
    private void updateVocCount(LambdaQueryWrapper<VocChapBookDO> vocChapBookWrapper) {
        List<VocChapBookDO> vocChapBookDOs
                = vocChapBookMapper.selectList(vocChapBookWrapper);


        List<Long> bookIds = vocChapBookDOs.stream()
                .map(vocChapBookDO -> vocChapBookDO.getBookId())
                .collect(Collectors.toList());

        LambdaUpdateWrapper<VocBookDO> vocBookDOLambdaUpdateWrapper
                = Wrappers.lambdaUpdate(VocBookDO.class)
                .in(VocBookDO::getId, bookIds)
                .setSql("voc_count=voc_count - 1");
        vocBookMapper.update(vocBookDOLambdaUpdateWrapper);


        List<Long> chapterIds = vocChapBookDOs.stream()
                .map(vocChapBookDO -> vocChapBookDO.getChapterId())
                .collect(Collectors.toList());
        LambdaUpdateWrapper<VocChapterDO> vocChapterDOLambdaUpdateWrapper = Wrappers.lambdaUpdate(VocChapterDO.class)
                .in(VocChapterDO::getId, chapterIds)
                .setSql("voc_count=voc_count - 1");
        vocChapterMapper.update(vocChapterDOLambdaUpdateWrapper);
    }


    @Override
    //指定单词的单词-章节-书籍关系列表
    public List<VocChapBookDTO> getVocRelations(Long vocId) {
        List<VocChapBookDO> vocRelations = vocChapBookMapper.getVocRelations(vocId);
        return vocConverter.vocChapBookDOs2DTOs(vocRelations);
    }

    @Override
    //分页查询单词列表 分页查询指定书籍中的单词列表
    public PageDTO<DisplayBookVocDTO> getDisplayBookVocsInfo(AppVocPageRequest pageRequest) {
        // 1. 查询书籍关联的单词ID列表
        QueryWrapper<VocChapBookDO> bookWrapper = new QueryWrapper<>();
        bookWrapper.select("DISTINCT voc_id")
                .eq("book_id", pageRequest.getBookId())
                .eq("is_deleted", 0);

        List<VocChapBookDO> bookRelations = vocChapBookMapper.selectList(bookWrapper);
        if (bookRelations.isEmpty()) {
            // 使用无参构造器创建空结果
            PageDTO<DisplayBookVocDTO> emptyPage = new PageDTO<>();
            emptyPage.setPageList(Collections.emptyList());
            emptyPage.setTotalCount(0L);
            return emptyPage;
        }

        // 提取单词ID集合
        Set<Long> vocIdSet = bookRelations.stream()
                .map(VocChapBookDO::getVocId)
                .collect(Collectors.toSet());

        // 2. 查询单词基本信息
        QueryWrapper<VocDO> vocWrapper = new QueryWrapper<>();
        vocWrapper.in("id", vocIdSet)
                .eq("is_deleted", 0);
        List<VocDO> vocList = vocMapper.selectList(vocWrapper);
        if (vocList.isEmpty()) {
            PageDTO<DisplayBookVocDTO> emptyPage = new PageDTO<>();
            emptyPage.setPageList(Collections.emptyList());
            emptyPage.setTotalCount(0L);
            return emptyPage;
        }

        // 3. 查询单词释义
        List<Long> vocIds = vocList.stream().map(VocDO::getId).collect(Collectors.toList());
        QueryWrapper<VocMeaningDO> meaningWrapper = new QueryWrapper<>();
        meaningWrapper.in("voc_id", vocIds)
                .eq("is_deleted", 0);
        List<VocMeaningDO> meanings = vocMeaningMapper.selectList(meaningWrapper);

        // 4. 按单词分组释义
        Map<Long, List<VocMeaningDO>> meaningMap = meanings.stream()
                .collect(Collectors.groupingBy(VocMeaningDO::getVocId));

        // 5. 设置释义到单词对象
        for (VocDO voc : vocList) {
            List<VocMeaningDO> vocMeanings = meaningMap.getOrDefault(voc.getId(), Collections.emptyList());
            voc.setInterpretations(vocMeanings);
        }

        // 6. 转换并返回分页结果
        List<DisplayBookVocDTO> dtos = vocConverter.vocDos2DisplayChapterVocDTOs(vocList);

        // 手动创建PageDTO对象
        PageDTO<DisplayBookVocDTO> result = new PageDTO<>();
        result.setPageList(dtos);
        result.setTotalCount((long) dtos.size());
        return result;
    }

    @Override
    //分页查询单词列表 分页查询指定章节中的单词列表
    public PageDTO<DisplayChapterDTO> getDisplayBookChapterVocsInfo(AppVocPageRequest pageRequest) {
        // 1. 根据bookId查询所有章节
        QueryWrapper<VocChapterDO> chapterWrapper = new QueryWrapper<>();
        chapterWrapper.eq("book_id", pageRequest.getBookId())
                .eq("is_deleted", 0)
                .orderByAsc("sort_by");
        List<VocChapterDO> chapterList = vocChapterMapper.selectList(chapterWrapper);
        long total = chapterList.size();

        if (chapterList.isEmpty()) {
            PageDTO<DisplayChapterDTO> emptyPage = new PageDTO<>();
            emptyPage.setPageList(Collections.emptyList());
            emptyPage.setTotalCount(0L);
            return emptyPage;
        }

        // 2. 获取所有章节ID
        List<Long> chapterIds = chapterList.stream()
                .map(VocChapterDO::getId)
                .collect(Collectors.toList());

        // 3. 查询章节-单词关系
        QueryWrapper<VocChapBookDO> relationWrapper = new QueryWrapper<>();
        relationWrapper.in("chapter_id", chapterIds)
                .eq("is_deleted", 0);
        List<VocChapBookDO> relations = vocChapBookMapper.selectList(relationWrapper);

        // 4. 获取所有单词ID
        List<Long> vocIds = relations.stream()
                .map(VocChapBookDO::getVocId)
                .distinct()
                .collect(Collectors.toList());

        // 构建章节-单词映射关系
        Map<Long, List<Long>> chapterVocMap = new HashMap<>();
        relations.forEach(relation -> {
            chapterVocMap.computeIfAbsent(relation.getChapterId(), k -> new ArrayList<>())
                    .add(relation.getVocId());
        });

        // 5. 批量查询单词详情
        List<VocDO> allVocList = vocIds.isEmpty() ?
                Collections.emptyList() :
                vocMapper.selectBatchIds(vocIds);

        // 6. 查询单词释义
        Map<Long, List<VocMeaningDO>> meaningMap = new HashMap<>();
        if (!vocIds.isEmpty()) {
            QueryWrapper<VocMeaningDO> meaningWrapper = new QueryWrapper<>();
            meaningWrapper.in("voc_id", vocIds)
                    .eq("is_deleted", 0);
            List<VocMeaningDO> meanings = vocMeaningMapper.selectList(meaningWrapper);

            meanings.forEach(meaning -> {
                meaningMap.computeIfAbsent(meaning.getVocId(), k -> new ArrayList<>())
                        .add(meaning);
            });
        }

        // 7. 组装章节单词数据
        Map<Long, DisplayChapterDTO> resultMap = new LinkedHashMap<>();
        for (VocChapterDO chapter : chapterList) {
            DisplayChapterDTO chapterDTO = vocConverter.vocChapterDO2displayChapterDTO(chapter);
            chapterDTO.setDisplayVocs(new ArrayList<>());
            resultMap.put(chapter.getId(), chapterDTO);
        }

        // 构建单词ID到单词对象的映射
        Map<Long, VocDO> vocMap = allVocList.stream()
                .collect(Collectors.toMap(VocDO::getId, Function.identity()));

        // 填充每个章节的单词列表
        relations.forEach(relation -> {
            Long chapterId = relation.getChapterId();
            Long vocId = relation.getVocId();

            DisplayChapterDTO chapterDTO = resultMap.get(chapterId);
            if (chapterDTO != null && vocMap.containsKey(vocId)) {
                VocDO vocDO = vocMap.get(vocId);

                // 设置单词释义
                List<VocMeaningDO> meanings = meaningMap.getOrDefault(vocId, Collections.emptyList());
                vocDO.setInterpretations(meanings);

                // 转换为DTO并添加到章节
                DisplayBookVocDTO vocDTO = vocConverter.vocDo2DisplayChapterVocDTO(vocDO);
                chapterDTO.getDisplayVocs().add(vocDTO);
            }
        });

        // 8. 返回分页结果（使用无参构造器和set方法）
        PageDTO<DisplayChapterDTO> resultPage = new PageDTO<>();
        resultPage.setPageList(new ArrayList<>(resultMap.values()));
        resultPage.setTotalCount(total);

        return resultPage;
    }

    @Override
    public VocDTO getVocDetail(Long vocId, Long userId) {

        VocDO vocDetail = vocMapper.getVocDetail(userId, vocId);
        List<UserVocExampleSentenceDO> userVocSentence = vocMapper.getUserVocExampleSentence(userId, vocId);
        vocDetail.setUserExamples(userVocSentence);

        LambdaQueryWrapper<UserFavoriteDO> favoriteWrapper = Wrappers.lambdaQuery(UserFavoriteDO.class)
                .eq(UserFavoriteDO::getUserId, userId)
                .eq(UserFavoriteDO::getVocId, vocId);
        // 获取用户是否收藏
        Long count = userFavoriteMapper.selectCount(favoriteWrapper);
        vocDetail.setFavorite(count > 0 ? 1 : 0);
        return vocConverter.vocDO2DTO(vocDetail);

    }

    @Override
    public UserBookStatisticsDTO getUserChooseCountInBook(Long userId, Long bookId) {
        return null;
    }

    @Override
    public void vocExcelValidate(MultipartFile file) throws IOException {
        // 文件基本检查
        if (file == null || file.isEmpty()) {
            throw new ExcelParseException(ResultCodeEnum.PARAM_ERROR, "Excel文件不能为空");
        }

        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null ||
                !(originalFilename.endsWith(".xlsx") || originalFilename.endsWith(".xls"))) {
            throw new ExcelParseException(ResultCodeEnum.PARAM_ERROR, "请上传Excel文件(.xlsx或.xls)");
        }

        vocExcelValidator.validate(templatePath, file.getInputStream());
    }

    @Override
    public ExcelAddOperateDTO addVocExcel(MultipartFile file, Long userId) throws IOException {
        Integer totalCount = vocExcelSaver.upload(file, VocExcelDTO.class, (data -> {
            VocDO vocDO = vocConverter.vocExcelDTO2VocDO(data);
            // 验证释义
            String interpretations = data.getInterpretations();
            List<VocMeaningDO> vocMeaningDOs = parseInterpretations(interpretations);
            vocDO.setInterpretations(vocMeaningDOs);
            // 验证例句
            String exampleSentences = data.getExampleSentences();
            List<ExampleSentenceDO> userVocExampleSentenceDOs = parseExamples(exampleSentences);
            vocDO.setExamples(userVocExampleSentenceDOs);
            // 验证书籍章节信息
            String bookInfo = data.getBookInfos();
            List<VocChapBookDO> vocChapBookDOs = parseBookInfo(vocDO.getContent(), bookInfo);
            VocExcelParsedDO vocExcelParsedDO = new VocExcelParsedDO();
            vocExcelParsedDO.setVoc(vocDO);
            vocExcelParsedDO.setVocChapBooks(vocChapBookDOs);
            return vocExcelParsedDO;
        }));
        ExcelAddOperateDTO excelAddOperateDTO = new ExcelAddOperateDTO();
        excelAddOperateDTO.setFileName(file.getOriginalFilename());
        excelAddOperateDTO.setTotalCount(totalCount);
        return excelAddOperateDTO;
    }

    private List<VocMeaningDO> parseInterpretations(String definitions) {
        List<VocMeaningDO> result = new ArrayList<>();
        if (definitions == null || definitions.trim().isEmpty()) {
            return result;
        }
        String[] definitionLines = splitByLineBreak(definitions);
        for (int i = 0; i < definitionLines.length; i++) {
            VocMeaningDO vocMeaningDO = new VocMeaningDO();
            String definition = definitionLines[i].trim();
            // 分离词性和释义内容
            int dotIndex = definition.indexOf('.');
            if (dotIndex > 0) {
                String partOfSpeech = definition.substring(0, dotIndex).trim(); // 词性
                vocMeaningDO.setType(partOfSpeech);
                String content = definition.substring(dotIndex + 1).trim(); // 释义内容
                vocMeaningDO.setInterContent(content);
//                log.debug("解析释义: 词性={}, 内容={}", partOfSpeech, content);
                result.add(vocMeaningDO);
            }
        }
        return result;
    }

    private String[] splitByLineBreak(String input) {
        if (input == null || input.isEmpty()) {
            return new String[0];
        }
        // 正则表达式匹配所有类型的换行符
        return input.split("\\r\\n|\\r|\\n");
    }
    private List<ExampleSentenceDO> parseExamples(String examples) {
        List<ExampleSentenceDO> result = new ArrayList<>();
        if (examples == null || examples.trim().isEmpty()) {
            return result;
        }
        String[] exampleLines = splitByLineBreak(examples);
        // 按照例句-翻译的顺序解析
        for (int i = 0; i < exampleLines.length; i += 2) {
            ExampleSentenceDO userVocExampleSentenceDO = new ExampleSentenceDO();
            String sentence = exampleLines[i].trim();
            userVocExampleSentenceDO.setContent(sentence);
            String translation = (i + 1 < exampleLines.length) ? exampleLines[i + 1].trim() : "";
            userVocExampleSentenceDO.setMeaning(translation);
            result.add(userVocExampleSentenceDO);
//            log.debug("解析例句: 句子={}, 翻译={}", sentence, translation);
        }
        return result;
    }

    private List<VocChapBookDO> parseBookInfo(String vocContent, String bookInfo) {
        List<VocChapBookDO> result = new ArrayList<>();
        String[] bookInfoSplits = splitByLineBreak(bookInfo);
        for (int i = 0; i < bookInfoSplits.length; i++) {
            VocChapBookDO vocChapBookDO = new VocChapBookDO();
            String[] parts = bookInfo.split("#");
            String bookName = parts[0].trim();
            vocChapBookDO.setBookName(bookName);
            vocChapBookDO.setVocName(vocContent);
            if (parts.length == 1) {
                // 验证书籍是否存在
                LambdaQueryWrapper<VocBookDO> bookQueryWrapper = new LambdaQueryWrapper<VocBookDO>()
                        .eq(VocBookDO::getName, bookName);
                VocBookDO vocBookDO = vocBookMapper.selectOne(bookQueryWrapper);
                vocChapBookDO.setBookId(vocBookDO.getId());
                return result;
            }
            if (parts.length == 2) {
                String chapterName = parts[1].trim();
                vocChapBookDO.setChapterName(chapterName);
                // 验证章节是否存在
                LambdaQueryWrapper<VocChapterDO> chapterQuery = new LambdaQueryWrapper<VocChapterDO>()
                        .eq(VocChapterDO::getBookName, bookName)
                        .eq(VocChapterDO::getChapterName, chapterName);
                VocChapterDO vocChapterDO = vocChapterMapper.selectOne(chapterQuery);
                vocChapBookDO.setBookId(vocChapterDO.getBookId());
                vocChapBookDO.setChapterId(vocChapterDO.getId());
            }
            result.add(vocChapBookDO);
        }
        return result;
    }
    @Override
    public DeleteVocFileOperateDTO deleteFile(Long id, String type, String name) {
        // 删除oss中的音频文件
        fileUploadService.deleteFile(name);

        LambdaUpdateWrapper<VocDO> updateWrapper = new LambdaUpdateWrapper<>();
        SFunction<VocDO, String> field = "uk".endsWith(type) ?
                VocDO::getUkPronounciation : VocDO::getUsPronounciation;
        updateWrapper.eq(VocDO::getId, id)
                .set(field, null);

        VocDO vocDO = vocMapper.selectById(id);
        DeleteVocFileOperateDTO deleteVocFileOperateDTO = new DeleteVocFileOperateDTO();
        deleteVocFileOperateDTO.setVocId(id);
        deleteVocFileOperateDTO.setContent(vocDO.getContent());
        deleteVocFileOperateDTO.setType(type);
        deleteVocFileOperateDTO.setFileName(name);

        return deleteVocFileOperateDTO;
    }

    @Override
    public DeleteVocRelationOperateDTO deleteVocRelation(Long id) {
        VocChapBookDO vocChapBookDO = vocChapBookMapper.selectById(id);
        vocChapBookMapper.deleteById(id);
        // 删除章节与书籍包含的单词数量
        if (vocChapBookDO.getChapterId()!= null) {
            // 有章节(此时一定是新增)
            vocMapper.updateChapterVocCount(vocChapBookDO.getChapterId(), -1);
        }
        vocMapper.updateBookVocCount(vocChapBookDO.getBookId(), -1);
        return vocConverter.toDeleteVocRelationOperateDTO(vocChapBookDO);
    }

    @Override
    public DeleteInterpretationOperateDTO deleteInterpretation(Long id) {
        VocMeaningDO vocMeaningDO = vocMeaningMapper.selectById(id);
        VocDO vocDO = vocMapper.selectById(vocMeaningDO.getVocId());

        vocMeaningMapper.deleteById(id);

        return vocConverter.toDeleteInterpretationOperateDTO(vocMeaningDO, vocDO.getContent());
    }

    @Override
    public DeleteVocExampleOperateDTO deleteExample(Long id) {
        ExampleSentenceDO sentenceDO = exampleSentenceMapper.selectById(id);
        VocDO vocDO = vocMapper.selectById(sentenceDO.getVocId());
        exampleSentenceMapper.deleteById(id);
        return vocConverter.toDeleteExampleOperateDTO(sentenceDO, vocDO.getContent());
    }

}
